/** FASSIT (Forms of Selective Attention in Intelligent Transportation Systems)
 * Computational Creativity and Digital Media
 * Cognitive and Media Systems Group
 * Centre for Informatics and Systems of the University of Coimbra (CISUC)
 *
 * Copyright (c) 2010-2013 University of Coimbra, Portugal
 * All rights reserved.
 */

package masterAgent.Knowledge;

import java.util.HashMap;

import masterAgent.DBmanager.DBConnection;
import masterAgent.DBmanager.DBManager;
import poi.Info.POI;
import poi.Info.POIwithSAMetrics;
import poi.Surprise.SurpriseDaysOff;
import poi.Surprise.SurprisePrice;
import poi.Surprise.SurpriseSchedule;
import poi.SurpriseCalculator.SurpriseCalculatorForPOI;
import poi.Uncertainty.UncertaintyDaysOff;
import poi.Uncertainty.UncertaintyPrice;
import poi.Uncertainty.UncertaintySchedule;
import poi.UncertaintyCalculator.UncertaintyCalculatorForPOI;
import agent.Context.Context;
import agent.Context.Goal;

/**
 * This class is used as an Interface to the Agent communicate with the
 * MasterAgent
 * 
 * @author Hernani Costa
 * @version 0.2 date: 11/02/2013
 */
public class MasterAgent {
	private DBManager manager;

	/**
	 * ------------------------------------------------------------------------
	 * Constructor class
	 * ------------------------------------------------------------------------
	 */
	public MasterAgent() {
		manager = new DBManager();
	}

	/**
	 * ------------------------------------------------------------------------
	 * Returns all the POIs within a radius for a specific Goal
	 * ------------------------------------------------------------------------
	 * 
	 * 
	 * @param context
	 *            - agent context
	 * @return an arrayList with all the POIs within the radius for a specific
	 *         goal
	 */
	public HashMap<Integer, POI> getPOIsNear(Context context) {
		return manager.getPOIsNear(context.getLocation(), context.getRadius(),
				context.getGoal());
	}

	/**
	 * ------------------------------------------------------------------------
	 * Returns the Master Agent Knowledge (including the Selective Attention
	 * Values)
	 * ------------------------------------------------------------------------
	 * 
	 * @param pois
	 *            - POIs without SA values
	 * @return POIs with SA values
	 */
	public HashMap<Integer, POIwithSAMetrics> getKnowledge(
			HashMap<Integer, POI> pois) {
		return getPOIsWithSAValues(pois);
	}

	/**
	 * ------------------------------------------------------------------------
	 * This method creates the new object POIwithSAMetrics. It converts
	 * automatically a list of POIs to a list of POIs With Selective Attention
	 * values
	 * ------------------------------------------------------------------------
	 * 
	 * @param pois
	 *            - the list of POIs to be converted
	 * @return POIwithSAMetrics - the resulted list of POIs with Selective
	 *         Attention values
	 */
	private HashMap<Integer, POIwithSAMetrics> getPOIsWithSAValues(
			HashMap<Integer, POI> pois) {
		// Surprise
		SurpriseCalculatorForPOI maSurprise = new SurpriseCalculatorForPOI(pois);

		HashMap<Integer, SurpriseSchedule> poiSurpriseSchedule = maSurprise
				.getPoiSurpriseSchedule();
		HashMap<Integer, SurpriseDaysOff> poiSurpriseDayOff = maSurprise
				.getPoiSurpriseDayOff();
		HashMap<Integer, SurprisePrice> poiSurprisePrice = maSurprise
				.getPoiSurprisePrice();

		// Uncertainty
		UncertaintyCalculatorForPOI maUncertainty = new UncertaintyCalculatorForPOI(
				pois);

		HashMap<Integer, UncertaintySchedule> poiUncertaintySchedule = maUncertainty
				.getPoiUncertaintySchedule();
		HashMap<Integer, UncertaintyDaysOff> poiUncertaintyDayOff = maUncertainty
				.getPoiUncertaintyDayOff();
		HashMap<Integer, UncertaintyPrice> poiUncertaintyPrice = maUncertainty
				.getPoiUncertaintyPrice();

		HashMap<Integer, POIwithSAMetrics> poisWithSAMetrics = new HashMap<Integer, POIwithSAMetrics>();

		int poiID = 0;
		POIwithSAMetrics tempPoiWithSA = null;

		for (POI poi : pois.values()) {
			poiID = poi.getPoiID();
			// System.err.println(poi.to_String());
			tempPoiWithSA = new POIwithSAMetrics(poi,
					poiSurprisePrice.get(poiID), poiSurpriseDayOff.get(poiID),
					poiSurpriseSchedule.get(poiID),
					poiUncertaintyPrice.get(poiID),
					poiUncertaintyDayOff.get(poiID),
					poiUncertaintySchedule.get(poiID));

			// System.err.println("POIid: "+poiID);
			// System.err.println(poiWithSurprise.to_String());
			poisWithSAMetrics.put(poiID, tempPoiWithSA);
			// poisWithSurprise.add(poiWithSurprise);
		}

		return poisWithSAMetrics;
	}

	/**
	 * ------------------------------------------------------------------------
	 * Intends to induce noise in the knowledge that is passed from the Master
	 * to the Agent
	 * ------------------------------------------------------------------------
	 * 
	 * @param pois - POIs without any noise
	 * @param context - the current user context
	 * @return POIs with noise
	 */
	public HashMap<Integer, POI> getNoisyPOIs(HashMap<Integer, POI> pois,
			Context context) {
		NoisyChannel noisyChannel = new NoisyChannel(pois, context);
		return noisyChannel.getNoisyPOIs();
	}

	/**
	 * ------------------------------------------------------------------------
	 * Only for debug purpose
	 * ------------------------------------------------------------------------
	 */
	public static void main(String args[]) {
		DBConnection connector = new DBConnection();

		POI poi = connector.getPOI(1507669);
		DBManager manager = new DBManager();

		HashMap<Integer, POI> pois = manager.getPOIsNear(poi.getLocation(),
				200, new Goal().getCoffee());
		
		MasterAgent k = new MasterAgent();
		
		HashMap<Integer, POIwithSAMetrics> poisWithSAValues = k
				.getKnowledge(pois);

		for (POIwithSAMetrics p : poisWithSAValues.values()) {
			System.out.println(p.to_String());

		}
	}
}
